﻿/*******************************************************************************************

JTolik Framework for Javascript 

Version 1.2.3

(c) 2010 Anatoli Tsyporyn. All rights reserved.

Can be distibuted under GNU/GPL license

*******************************************************************************************/

/*
------------------------------ JTDOM ------------------------------------------------------
*/


function $JTVersion () {
   return '1.2.2';
}


//Returns element by ID
function $JT(id)
{
    if (document.getElementById(id) != null)
        return document.getElementById(id);

}

/*
----- Blur Event Handling
*/

//Sets the only handler to blur event of the control (control group)

function $JTBlur(arrayID, func)
{
    if ($JT(arrayID) != null)
    {
        $JT(arrayID).onblur = func;
        return null;
    }

    for (var i = 0; i < arrayID.length; i++)
    {
        $JT(arrayID[i]).onblur = func;
    }

    return null;
}

//Adds handler to blur event of the control (control group)

function $JTBlurAdd(arrayID, func)
{
    if ($JT(arrayID) != null)
    {
        $JT(arrayID).addEventListener('blur', func);

        return null;
    }

    for (var i = 0; i < arrayID.length; i++)
    {
        $JT(arrayID[i]).addEventListener('blur', func);
    }

    return null;
}

//Sets the only handler to blur event of the control (control group) with the interval

function $JTBlurI(arrayID, func, interval)
{
    if ($JT(arrayID) != null)
    {
        $JT(arrayID).onblur = function() { setTimeout(function() { func.call(); }, interval); };

        return null;
    }

    for (var i = 0; i < arrayID.length; i++)
    {
        $JT(arrayID[i]).onblur = function() { setTimeout(function() { func.call(); }, interval); };
    }

    return null;
}

//Adds handler to blur event of the control (control group) with the interval

function $JTBlurAddI(arrayID, func, interval)
{
    if ($JT(arrayID) != null)
    {
        $JT(arrayID).addEventListener('blur', function() { setTimeout(function() { func.call(); }, interval); });

        return null;
    }

    for (var i = 0; i < arrayID.length; i++)
    {
        $JT(arrayID[i]).addEventListener('blur', function() { setTimeout(function() { func.call(); }, interval); });
    }

    return null;
}

/*
----- Focus Event Handling
*/

//Sets the only handler to focus event of the control (control group)

function $JTFocus(arrayID, func)
{
    if ($JT(arrayID) != null)
    {
        $JT(arrayID).onfocus = func;

        return null;
    }

    for (var i = 0; i < arrayID.length; i++)
    {
        $JT(arrayID[i]).onfocus = func;
    }

    return null;
}

//Sets the only handler to focus event of the control (control group) with the interval

function $JTFocusI(arrayID, func, interval)
{
    if ($JT(arrayID) != null)
    {
        $JT(arrayID).onfocus = function() { setTimeout(function() { func.call(); }, interval); };

        return null;
    }

    for (var i = 0; i < arrayID.length; i++)
    {
        $JT(arrayID[i]).onfocus = function() { setTimeout(function() { func.call(); }, interval); };
    }

    return null;
}

//Adds handler to focus event of the control (control group)

function $JTFocusAdd(arrayID, func)
{
    if ($JT(arrayID) != null)
    {
        $JT(arrayID).addEventListener('focus', func);

        return null;
    }

    for (var i = 0; i < arrayID.length; i++)
    {
        $JT(arrayID[i]).addEventListener('focus', func);
    }

    return null;
}

//Adds handler to focus event of the control (control group) with the interval

function $JTFocusAddI(arrayID, func, interval)
{
    if ($JT(arrayID) != null)
    {
        $JT(arrayID).addEventListener('focus', function() { setTimeout(function() { func.call(); }, interval); });

        return null;
    }

    for (var i = 0; i < arrayID.length; i++)
    {
        $JT(arrayID[i]).addEventListener('focus', function() { setTimeout(function() { func.call(); }, interval); });
    }

    return null;
}

/*
----- Change Event Handling
*/

//Sets the only handler to change event of the control (control group)

function $JTChange(arrayID, func)
{
    if ($JT(arrayID) != null)
    {
        $JT(arrayID).onchange = func;

        return null;
    }

    for (var i = 0; i < arrayID.length; i++)
    {
        $JT(arrayID[i]).onchange = func;
    }

    return null;
}

//Sets the only handler to focus event of the control (control group) with the interval

function $JTChangeI(arrayID, func, interval)
{
    if ($JT(arrayID) != null)
    {
        $JT(arrayID).onchange = function() { setTimeout(function() { func.call(); }, interval); };

        return null;
    }

    for (var i = 0; i < arrayID.length; i++)
    {
        $JT(arrayID[i]).onchange = function() { setTimeout(function() { func.call(); }, interval); };
    }

    return null;
}

//Adds handler to change event of the control (control group)

function $JTChangeAdd(arrayID, func)
{
    if ($JT(arrayID) != null)
    {
        $JT(arrayID).addEventListener('change', func);

        return null;
    }

    for (var i = 0; i < arrayID.length; i++)
    {
        $JT(arrayID[i]).addEventListener('change', func);
    }

    return null;
}

//Adds handler to change event of the control (control group) with the interval

function $JTChangeAddI(arrayID, func, interval)
{
    if ($JT(arrayID) != null)
    {
        $JT(arrayID).addEventListener('change', function() { setTimeout(function() { func.call(); }, interval); });

        return null;
    }

    for (var i = 0; i < arrayID.length; i++)
    {
        $JT(arrayID[i]).addEventListener('change', function() { setTimeout(function() { func.call(); }, interval); });
    }

    return null;
}

/*
----- Universal Event Handling
*/

function $JTHandlerAdd(arrayID, event, func)
{
    if ($JT(arrayID) != null)
    {
        $JT(arrayID).addEventListener(event, func);

        return null;
    }

    for (var i = 0; i < arrayID.length; i++)
    {
        $JT(arrayID).addEventListener(event, func);
    }

    return null;
}

function $JTHandlerAddI(arrayID, event, func, interval)
{
    if ($JT(arrayID) != null)
    {
        $JT(arrayID).addEventListener(event, function() { setTimeout(function() { func.call(); }, interval); });

        return null;
    }

    for (var i = 0; i < arrayID.length; i++)
    {
        $JT(arrayID[i]).addEventListener(event, function() { setTimeout(function() { func.call(); }, interval); });
    }

    return null;
}

function $JTHandlersAdd(arrayID, events, func)
{
    if ($JT(arrayID) != null)
    {
        for (var i = 0; i < events.length; i++)
        {
            $JT(arrayID).addEventListener(events[i], func);
        }

        return null;
    }

    for (var i = 0; i < arrayID.length; i++)
    {
        for (var j = 0; j < events.length; j++)
        {
            $JT(arrayID[i]).addEventListener(events[j], func);
        }
    }
}

function $JTHandlersAddI(arrayID, events, func)
{
    if ($JT(arrayID) != null)
    {
        for (var i = 0; i < events.length; i++)
        {
            $JT(arrayID).addEventListener(events[i], function() { setTimeout(function() { func.call(); }, interval); });
        }

        return null;
    }

    for (var i = 0; i < arrayID.length; i++)
    {
        for (var j = 0; j < events.length; j++)
        {
            $JT(arrayID[i]).addEventListener(events[j], function() { setTimeout(function() { func.call(); }, interval); });
        }
    }
}



//Gets the first parent object with the given CSS class
function JTGetFirstParentByClass(child, className, strictCheck)
{
    className = JTTrim(className);

    while (child.parentNode != null)
    {
        var pClassName = child.parentNode.className;

        if (strictCheck == true)
        {
            if (pClassName == className)
            {
                return child.parentNode;
            }
            else
            {
                if (child.parentNode != null) child = child.parentNode; else return null;
            }
        }
        else
        {
            if (JTContains(pClassName, className) == true)
            {
                return child.parentNode;
            }
            else
            {
                if (child.parentNode != null) child = child.parentNode; else return null;
            }
        }
    }

    return null;
}

//Gets the first parent object with the given CSS class
function JTGetFirstParentByClassUsingID(childID, className, strictCheck)
{
    className = JTTrim(className);

    var child = document.getElementById(childID);

    if (child == null) return null;

    while (child.parentNode != null)
    {
        var pClassName = child.parentNode.className;

        if (strictCheck == true)
        {
            if (pClassName == className)
            {
                return child.parentNode;
            }
            else
            {
                if (child.parentNode != null) child = child.parentNode; else return null;
            }
        }
        else
        {
            if (JTContains(pClassName, className) == true)
            {
                return child.parentNode;
            }
            else
            {
                if (child.parentNode != null) child = child.parentNode; else return null;
            }
        }
    }
    
    return null;
}

//Gets the first child with the given CSS class
function JTGetFirstChildByClassUsingID(childID, className, strictCheck)
{
    className = JTTrim(className);

    var child = document.getElementById(childID);

    if (child == null) return null;

    while (child.childNodes.length>0)
    {
        for (var i = 0; i < child.childNodes.length; i++)
        {
            var pClassName = child.childNodes[i].className;

            if (strictCheck == true)
            {
                if (pClassName == className)
                {
                    return child.childNodes[i];
                }
                else
                {
                    if (child.parentNode != null) child = child.childNodes[i]; else return null;
                }
            }
            else
            {
                if (JTContains(pClassName, className) == true)
                {
                    return child.childNodes[i];
                }
                else
                {
                    if (child.parentNode != null) child = child.childNodes[i]; else return null;
                }
            }
        }
    }

    return null;
}



//Generates new GUID of the object
function JTGuid()
{
    var S4 = function()
    {
        return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
    };
    return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
}

/*---------------------------- JTCARET ----------------------------------------------------*/

// Returns the caret (cursor) position of the specified text field.
// Return value range is 0-oField.length.
function JTCaretGetPosition(oField)
{
    // Initialize
    var iCaretPos = 0;

    // IE Support
    if (document.selection)
    {
        // Set focus on the element
        oField.focus();

        // To get cursor position, get empty selection range
        var oSel = document.selection.createRange();

        // Move selection start to 0 position
        oSel.moveStart('character', -oField.value.length);

        // The caret position is selection length
        iCaretPos = oSel.text.length;
    }

    // Firefox support
    else if (oField.selectionStart || oField.selectionStart == '0')
        iCaretPos = oField.selectionStart;

    // Return results
    return (iCaretPos);
}

//  Sets the caret (cursor) position of the specified text field.
//  Valid positions are 0-oField.length.
function JTCaretSetPosition(oField, iCaretPos)
{
    // IE Support
    if (document.selection)
    {
        // Set focus on the element
        oField.focus();

        // Create empty selection range
        var oSel = document.selection.createRange();

        // Move selection start and end to 0 position
        oSel.moveStart('character', -oField.value.length);

        // Move selection start and end to desired position
        oSel.moveStart('character', iCaretPos);
        oSel.moveEnd('character', 0);
        oSel.select();
    }

    // Firefox support
    else if (oField.selectionStart || oField.selectionStart == '0')
    {
        oField.selectionStart = iCaretPos;
        oField.selectionEnd = iCaretPos;
        oField.focus();
    }
}

/*
--------------------------------- JTREFLECTION ----------------------------------------------
*/


//Returns the names of all the obj's variables and functions in a sorted array

function JTGetMembers(obj)
{
    var members = new Array();
    var i = 0;

    for (var member in obj)
    {
        members[i] = member;
        i++;
    }

    return members.sort();
}

//Returns the names of all the obj's variables and functions in a sorted JTList

function JTGetMembersToList(obj)
{
    var members = JTGetMembers(obj);

    var list = new JTList();

    list.addRangeFromArray(members);

    return list;
}

//Gets if item is method of the specified object or not
function JTIsMethod(obj, item)
{
	if (obj[item]!=null)
	{
	    if (obj[item].call != null)
	    {
	        return true;
	    }
	    else
	    {
	        return false;
	    }
    }
    else
    {
    	return null;
    }
}

//Prints infromation about the object
function JTPrintObject(obj, showIt) {
  
    var list = new JTGetMembersToList(obj);
    var str ;
    str = "<h1>Object reflection information:</h1><hr>";
    for (var i=0; i<list.length; i++)
    {
    	var res = JTIsMethod(obj,list.$(i))
    	if (res == true)
    	{
    		str = str + "<br><b> Method: </b>" + list.$(i) ;	
    	}
    	
    	if (res == false)
    	{
    		str = str + "<br><b> Property: </b>" + list.$(i);	
    	}    	
    	
    	if (res == null)
    	{
    		str = str + "<br> Unknown: " + list.$(i);	
    	}
    }  
    if (showIt == true) document.write(str);
    return str;
}

/*
------------------------------ JTLIST ------------------------------------------------------

JTolik full featured implementation of .NET list in java script

*/

function JTList()
{

    this.list = [];
    this.length = 0;

    this.addItem = function(item) { this.list[this.length] = item; this.length++; return null; }
    this.addRange = function(items)
    {

        for (var i = 0; i < items.length; i++)
        {
            this.addItem(items.item(i));
        }
    }

    this.addRangeFromArray = function(items)
    {

        for (var i = 0; i < items.length; i++)
        {
            this.addItem(items[i]);
        }
    }


    this.item = function(index) { if (index > this.length) return null; else return this.list[index]; }
    this.clear = function() { this.length = 0; }
    this.copy = function()
    {

        var jtList = new JTList();

        for (var i = 0; i < this.length; i++)
        {
            jtList.addItem(this.list[i]);
        }

        return jtList;

    }

    this.contains = function(item)
    {
        for (var i = 0; i < this.length; i++)
        {
            if (item == this.list[i]) return true;
        }
        return false;
    }

    this.indexOf = function(item)
    {
        for (var i = 0; i < this.length; i++)
        {
            if (item == this.list[i]) return i;
        }
        return -1;
    }

    this.foreach = function(action)
    {
        for (var i = 0; i < this.length; i++)
        {
            var res = action.call(this, this.list[i]);
            if (res != null) this.list[i] = res;
        }
    }

    this.insert = function(item, index)
    {
        if (!JTIsNumber(index)) return null;
        if (index < this.length)
        {
            this.list.splice(index, 0, item);
            this.length++;
        }
    }

    this.insertRange = function(items, index)
    {
        var newItems = items; //= items; 
        if (index < this.length)
        {
            for (var i = 0; i < newItems.length; i++)
            {
                this.insert(newItems.item(i), (index + i));
            }
        }

    }

    this.lastIndexOf = function(item)
    {

        for (var i = this.length - 1; i >= 0; i--)
        {
            if (item == this.list[i]) return i;
        }

        return -1;
    }

    this.removeAt = function(index)
    {
        if (!JTIsNumber(index)) return null;
        if (index < this.length)
        {
            this.list.splice(index, 1);
            this.length--;
        }

    }

    this.remove = function(item)
    {

        for (var i = 0; i < this.length; i++)
        {
            if (item == this.list[i])
            {
                this.removeAt(i);
                return i;
            }
        }

        return -1;
    }

    this.removeAll = function(item)
    {
        var k = 0;

        for (var i = 0; i < this.length; i++)
        {
            if (item == this.list[i])
            {
                this.removeAt(i);
                this.length--;
                k++;
            }
        }

        return k;
    }

    this.removeRange = function(start, count)
    {
        var k = 0;
        if (!JTIsNumber(start)) return null;
        if (!JTIsNumber(count)) return null;

        if (start + count >= this.length) return null;

        for (var i = start; i <= start + count; i++)
        {
            if (k <= count) { this.removeAt(i - k); k++; } else { return null; }
        }

    }

    this.getRange = function(start, end)
    {
        if ((start < 0) || (start > end)) return null;
        if ((end < 0) || (end > this.length)) return null;

        var newList = new JTList();

        for (var i = start; i < end; i++)
        {
            newList.addItem(this.list[i]);
        }

        return newList;
    }

    this.toArray = function() { return list; }

    this.printList = function()
    {

        for (var i = 0; i < this.length; i++)
        {
            document.writeln(this.list[i].toString());
        }


    }

    this.sort = function(func)
    {

        if (func == null)
        {
            this.list.sort();
        }
        else
        {
            this.list.sort(func);
        }

    }
    
    this.count = function()
    {
       return this.length;
    }

    this.dispose = function()
    {
        for (var i = 0; i < this.length; i++)
        {
            delete this.list[i];
        }
    }

    this.$ = function(index) { if (index > this.length) return null; else return this.list[index]; }


}

/*---------------------------- JTKEYVALUEPAIR -----------------------------------------------*/

function JTKeyValuePair(_key, _value)
{
    this.key = _key;
    this.value = _value;
}

/*---------------------------- JTCLASS -------------------------------------------------------*/

function JTClass(inherits)
{
    this.properties = new JTList();
    this.methods = new JTList();
    
    if (inherits != null)
    {     
        if (inherits.properties != null)
        {
            for (var i = 0; i < inherits.properties.length; i++)
            {
                this.properties.addItem(inherits.properties.$(i));
                this[inherits.properties.$(i)] = inherits[inherits.properties.$(i)];
            }
        }
        if (inherits.methods != null)
            {
                for (var i = 0; i < inherits.methods.length; i++)
                {
                    this.methods.addItem(inherits.methods.$(i));
                    this[inherits.methods.$(i)] = inherits[inherits.methods.$(i)];
                }
            }

        if ((inherits.methods == null)&(inherits.properties == null))
            {
                var objReflectionList = JTGetMembersToList(inherits);

                for (var i = 0; i < objReflectionList.length; i++)
                {
                	var type = JTIsMethod(inherits, objReflectionList.$(i));
                    if (type == true)
                    {
                        this.methods.addItem(objReflectionList.$(i));
                        this[objReflectionList.$(i)] = inherits[objReflectionList.$(i)];
                    }
                    if (type == false)
                    { 
                        this.properties.addItem(objReflectionList.$(i));
                        this[objReflectionList.$(i)] = inherits[objReflectionList.$(i)];
                    }                
                    
                }

            }
        
    }


    this.Property = function (name, value, overrides) {
        if (!this.properties.contains(name)) {
            this[name] = value;
            this.properties.addItem(name);
            return true;
        }
        else {
            if (overrides == true) {
                this[name] = func;
                this.methods.addItem(name);
                return true;
            }
            return false;
        }
    }

    this.Void = function (name, overrides, func) {
        if (!this.methods.contains(name)) {
            this[name] = func;
            this.methods.addItem(name);
            return true;
        }
        else {
            if (overrides == true) {
                this[name] = func;
                this.methods.addItem(name);
                return true;
            }

            return false;
        }
    }

}

/*
------------------------------ JTSTRINGS ------------------------------------------------------
*/

//Removes leading whitespaces
function JTLTrim(value)
{

    var re = /\s*((\S+\s*)*)/;
    return value.replace(re, "$1");
    var t = new JTList()

}

//Removes ending whitespaces
function JTRTrim(value)
{

    var re = /((\s*\S+)*)\s*/;
    return value.replace(re, "$1");

}

//Removes leading and ending whitespaces
function JTTrim(value)
{

    return JTLTrim(JTRTrim(value));

}

//Gets is one string is a substring of another one
function JTContains(value, what)
{
    var strValue = new String(value);

    if (strValue.indexOf(what, 0) > -1)
    {
        return true;
    }
    else
        return false;

}

//Validate URL for correctness
function JTValidateURL(url)
{
    var RegExp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;

    return RegExp.test(url);
}

//Checks e-mail with regular expression
function JTValidateEMail(inputData)
{
    var reg = new RegExp(/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/);
    var inp = inputData;

    return reg.test(inp);
}


/*
------------------------------ JTNUMBERS ------------------------------------------------------
*/

//Checks if input data is a number
function JTIsNumber(inputData)
{
    return (!isNaN(inputData));
}

//Leaves only numbers in the 
function JTToNumeric(inputData)
{
    var strInput = new String(inputData);
    var strResult = new String();

    for (var i = 0; i < strInput.length; i++)
    {
        if (JTIsNumber(strInput.charAt(i)))
        {
            strResult = strResult + strInput.charAt(i);
        }
    }

    return strResult;
}

/*
------------------------------ JTDATES ------------------------------------------------------
*/

//Gets if dates interval is correct or not
function JTValidateDateInterval(monthStart, yearStart, monthEnd, yearEnd)
{

    if (!IsNumberRule(yearStart)) return false;
    if (!IsNumberRule(yearEnd)) return false;

    if (yearStart > yearEnd) return false;
    if ((yearStart == yearEnd) & (monthStart > monthEnd)) return false;

    var dateNow = new Date();
    var yearNow = dateNow.getFullYear();
    var monthNow = dateNow.getMonth();

    if (yearEnd > yearNow) return false;
    if ((yearEnd == yearNow) & (monthEnd > monthNow)) return false;

    if (yearStart > yearNow) return false;
    if ((yearStart == yearNow) & (monthStart > monthNow)) return false;

    if ((monthStart > 12) || (monthStart < 1)) return false;
    if ((monthEnd > 12) || (monthEnd < 1)) return false;

    return true;
}


//Checks the data by giving day, month and year as input parameters
function JTIsCorrectDate(day, month, year)
{

    if (day == '') return false;
    if (month == '') return false;
    if (year == '') return false;

    if ((!JTIsNumber(day)) || (!JTIsNumber(month)) || (!JTIsNumber(year))) return false;

    var dateNow = new Date();

    var dayNow = dateNow.getDay();
    var monthNow = dateNow.getMonth();
    var yearNow = dateNow.getFullYear();

    dateNow = Date.UTC(yearNow, monthNow, dayNow, 0, 0, 0);
    dateUser = Date.UTC(year, month - 1, day, 0, 0, 0);

    if (dateUser > dateNow)
    {
        return false;
    }

    switch (month)
    {
        case "1", "3", "5", "7", "8", "10", "12":
            {
                if ((day > 31) || (day < 1))
                {
                    return false;
                }
                break;
            }

        case "4", "6", "9", "11":
            {
                if ((day > 30) || (day < 1))
                {
                    return false;
                }
                break;
            }
        case "2":
            {
                if (JTDateDaysInFebruary(year) < day)
                {
                    return false;
                }

                if (day < 1) return false;
            }

    }

    return true;
}


//Checks day count in febrary
function JTDateDaysInFebruary(year)
{
    // February has 29 days in any year evenly divisible by four,
    // EXCEPT for centurial years which are not also divisible by 400.
    return (((year % 4 == 0) && ((!(year % 100 == 0)) || (year % 400 == 0))) ? 29 : 28);
}